package repositorioJuego;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import compartido.Usuario;

import persistencia.carreras.ObservadorDeCarreraPrintStream;
import persistencia.carreras.ObservadorDeCarreraSVG;

import modelo.carrera.Carrera;
import modelo.carrera.Jugador;
import modelo.carrera.ObservadorDeCarrera;
import modelo.carrera.comparadores.CarreraFechaLargadaComparador;

import modelo.escenario.Ciudad;
import modelo.geometria.Vector;

public class RepositorioJuegoEnMemoria implements IRepositorioJuego{
	
	
	private LinkedHashMap<String, Carrera> listaCarrera;
	private HashMap<String,Usuario> usuarios;
	Juego juego;
	private long identificador; 

	//	 Patron singleton
	static private RepositorioJuegoEnMemoria repositorio = null;

	private RepositorioJuegoEnMemoria() {
    	this.identificador = 10;
    	crearCarreras();
    	juego = new Juego(listaCarrera);    	  
   	}

    static public RepositorioJuegoEnMemoria getRepositorioJuego() {
        if (repositorio == null) {
            repositorio = new RepositorioJuegoEnMemoria();
        }
        return repositorio;
    }

    protected Map<String, Usuario> getUsuarios() {
    	if (usuarios == null) {
    		usuarios = new HashMap<String, Usuario>();
    		
    		usuarios.put("admin", new Usuario("admin", "admin"));
    		usuarios.put("florencia", new Usuario("florencia","florencia"));
    	}
    	return usuarios;
    }
    
    private void ordenarLista(){

    	LinkedHashMap<String,Carrera> newMap = new LinkedHashMap<String,Carrera>();

		ArrayList<Carrera> listaValores = new ArrayList<Carrera>(this.listaCarrera.values());
		Collections.sort(listaValores,new CarreraFechaLargadaComparador());
		Iterator<Carrera> it = listaValores.iterator();
		Carrera carrera = null;
		while(it.hasNext())
		{
			carrera = (Carrera) it.next();
			for(Map.Entry<String,Carrera> k : this.listaCarrera.entrySet()){
				if(carrera == k.getValue()){
					newMap.put((String)k.getKey(),(Carrera) carrera);
				}
			}
		}
		this.listaCarrera.clear();
		this.listaCarrera.putAll(newMap);
    }    
   
    private void crearCarreras(){

    	File directorio = new File("src/persistencia/carreras/pruebas/carrera1");
    	listaCarrera = new LinkedHashMap<String, Carrera>();
    	
    	DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");    	
    	Date fechaLargada = null;
		try {
			fechaLargada = df.parse("20/12/09 20:17:45");
		} catch (ParseException e) {

		}
		
		Vector puntoInicialCarreraUno = new Vector(12,3);
		Vector puntoFinalCarreraUno = new Vector(35,18);
		
		Carrera carrera = new Carrera(this.identificador, Ciudad.getCiudad(),fechaLargada, puntoInicialCarreraUno, puntoFinalCarreraUno);
		
		PrintStream salida = null;
		try {
			salida = new PrintStream(directorio.getAbsoluteFile()+File.separator+"Carrera1.xml");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	
		ObservadorDeCarrera observador = new ObservadorDeCarreraPrintStream(salida);
		ObservadorDeCarrera simulacion = new ObservadorDeCarreraSVG(directorio.getAbsolutePath());
		carrera.addObserver(observador);
		carrera.addObserver(simulacion);
				
		listaCarrera.put((String)String.valueOf(this.identificador),(Carrera)carrera);

//		 Carrera 2					
		try {
			fechaLargada = df.parse("17/12/09 20:28:45");
		} catch (ParseException e) {}

		this.identificador++;
		
		Vector puntoInicialCarreraDos = new Vector(45,3);
		Vector puntoFinalCarreraDos = new Vector(41,32);
		
		Carrera carrera2 = new Carrera(this.identificador, Ciudad.getCiudad(),fechaLargada, puntoInicialCarreraDos, puntoFinalCarreraDos);
		
		PrintStream salida2 = null;
		try {
			salida2 = new PrintStream(directorio.getAbsoluteFile()+File.separator+"Carrera2.xml");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	
		ObservadorDeCarrera observador2 = new ObservadorDeCarreraPrintStream(salida2);
		ObservadorDeCarrera simulacion2 = new ObservadorDeCarreraSVG(directorio.getAbsolutePath());
		carrera.addObserver(observador2);
		carrera.addObserver(simulacion2);
				
		listaCarrera.put((String)String.valueOf(this.identificador),(Carrera)carrera2);
		
		ordenarLista();
    }   
    
	public List<Jugador> obtenerListaGanadores(String idCarrera){
		return( getCarrera(idCarrera).getJugadores());
	}

	public List<Carrera> CarreraParaMostrar(){
		
		int cantidad = 0;
		Date fechaMayor = null;
		Date fechaMenor = null;
		Date fechaLargada;
		Carrera carrera;
		Date fechaActual = new java.util.Date();
		List<Carrera> listaAMostrar = new ArrayList<Carrera>();
		listaAMostrar.addAll(listaCarrera.values());
		
		while(cantidad < listaAMostrar.size()){
			carrera = (Carrera)listaAMostrar.get(cantidad);
			fechaLargada = carrera.getHorarioLargada();

			if (fechaActual.compareTo(fechaLargada) > 0){
				fechaMayor = fechaActual;
				fechaMenor = fechaLargada;
			}else{
				fechaMayor = fechaLargada;
				fechaMenor = fechaActual;
			}

			long diferenciaMils = fechaMayor.getTime() - fechaMenor.getTime();			
			
			// 30 min = 1800000 milisegundo
			if (( diferenciaMils <= 1800000 && !carrera.getFinalizada())|| carrera.getFinalizada()){
				listaAMostrar.remove(carrera);				
			}
			cantidad++;
		}		
		
		return listaAMostrar ;
	}

	// Agregar al Jugador en la carrera que se incribio
	public void addJugador(Jugador jugador,String idCarrera){	
	
		if (idCarrera != null){
			Carrera carrera = getCarrera(idCarrera);
			if ( carrera != null){
				carrera.agregarJugador(jugador);	
				
			}
		}
	}	
    
	
	public Carrera getCarrera(String idCarrera){
				
		return ((Carrera)listaCarrera.get((String)idCarrera));
	}

	@Override
	public void addUsuario(Usuario usuarioNuevo) {
		if (! getUsuarios().containsKey(usuarioNuevo.getIdentificador()) )
				getUsuarios().put(usuarioNuevo.getIdentificador(),usuarioNuevo);
	}
	
	@Override
	public void removeUsuario(Usuario usuarioAEliminar) {
		Usuario existente = getUsuario(usuarioAEliminar.getIdentificador());
		if ( (existente != null) && (existente.compareTo(usuarioAEliminar) == 0) )
			getUsuarios().remove(existente.getIdentificador());
	}

	@Override
	public Usuario getUsuario(String nombre) {
		return getUsuarios().get(nombre);
	}	
}
